package demo.common.dao;

import demo.common.model.PagingCondition;
import demo.common.model.SqlCondition;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.builder.annotation.ProviderContext;

import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.util.List;

/**
 * Created by llq on 2017/12/5.
 */
@Mapper
public interface BaseDao<T, ID> {

    @SelectProvider(type = BaseDaoProvider.class, method = "pagingData")
    List<T> pagingData(PagingCondition pagingCondition);

    @SelectProvider(type = BaseDaoProvider.class, method = "pagingTotal")
    int pagingTotal(PagingCondition pagingCondition);

    @SelectProvider(type = BaseDaoProvider.class, method = "find")
    List<T> findAll();

    @SelectProvider(type = BaseDaoProvider.class, method = "findByCondition")
    List<T> find(SqlCondition condition);

    @SelectProvider(type = BaseDaoProvider.class, method = "get")
    T get(ID id);

    @InsertProvider(type = BaseDaoProvider.class, method = "insert")
    void insert(T entity);

    @InsertProvider(type = BaseDaoProvider.class, method = "replace")
    void replace(T entity);

    @UpdateProvider(type = BaseDaoProvider.class, method = "updateByAnnotation")
    void updateByAnnotation(T entity, Class<? extends Annotation> updateAnnotation);

    @DeleteProvider(type = BaseDaoProvider.class, method = "delete")
    void delete(String id);

    public static class BaseDaoProvider {

        private Class ModelType(ProviderContext providerContext) {
            Class mapperType = providerContext.getMapperType();
            ParameterizedType genericSuperclass = (ParameterizedType)mapperType.getGenericInterfaces()[0];
            return (Class) genericSuperclass.getActualTypeArguments()[0];
        }

        public String pagingData(PagingCondition pagingCondition, ProviderContext providerContext) {
            Class entityClass = ModelType(providerContext);
            return BaseProvider.EntitySQL.from(entityClass).pagingData(pagingCondition);
        }

        public String pagingTotal(PagingCondition pagingCondition, ProviderContext providerContext) {
            Class entityClass = ModelType(providerContext);
            return BaseProvider.EntitySQL.from(entityClass).pagingTotal(pagingCondition);
        }

        public String find(ProviderContext providerContext) {
            Class entityClass = ModelType(providerContext);
            return BaseProvider.EntitySQL.from(entityClass).find();
        }

        public String findByCondition(SqlCondition sqlCondition, ProviderContext providerContext) {
            Class entityClass = ModelType(providerContext);
            return BaseProvider.EntitySQL.from(entityClass).find(sqlCondition);
        }

        public String get(ProviderContext providerContext) {
            Class entityClass = ModelType(providerContext);
            return BaseProvider.EntitySQL.from(entityClass).getSQL();
        }

        public String insert(ProviderContext providerContext) {
            Class entityClass = ModelType(providerContext);
            return BaseProvider.EntitySQL.from(entityClass).insertSQL();
        }

        public String delete(ProviderContext providerContext) {
            Class entityClass = ModelType(providerContext);
            return BaseProvider.EntitySQL.from(entityClass).deleteSQL();
        }

        public String replace(ProviderContext providerContext) {
            Class entityClass = ModelType(providerContext);
            return BaseProvider.EntitySQL.from(entityClass).replaceSQL();
        }
        public String updateByAnnotation(Object entity, Class<? extends Annotation> updateAnnotation, ProviderContext providerContext) {
            Class entityClass = ModelType(providerContext);
            return BaseProvider.EntitySQL.from(entityClass).updateByAnnotationSQL(updateAnnotation, "param1.");
        }

    }

}
